package com.hgl.bi.web.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hgl.bi.web.entity.StatsEntity;
import com.hgl.bi.web.mapper.AnalyzeMapper;
import com.hgl.bi.web.mapper.CleanMapper;
import com.hgl.bi.web.mapper.StatsMapper;
import com.hgl.bi.web.model.vo.StatsVo;
import com.hgl.bi.web.service.StatsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @program: BI
 * @description: 统计服务实现层
 * @author: hgl
 * @create: 2025-02-28 15:40
 */
@Service
public class StatsServiceImpl extends ServiceImpl<StatsMapper, StatsEntity>
        implements StatsService {

    @Autowired
    private StatsMapper statsMapper;

    @Autowired
    private CleanMapper cleanMapper;
    @Autowired
    private AnalyzeMapper analyzeMapper;

    @Override
    public List<StatsVo> getStats(String range) {
        // 1. 计算时间范围
        LocalDateTime[] dateRange = calculateDateRange(range);
        LocalDateTime start = dateRange[0];
        LocalDateTime end = dateRange[1];

        // 2. 查询原始数据
        List<Map<String, Object>> cleanData = cleanMapper.getCleanStats(start, end);
        List<Map<String, Object>> analyzeData = analyzeMapper.getAnalStats(start, end);

        // 3. 合并并补全数据
        return mergeData(start, end, cleanData, analyzeData);
    }

    // 计算时间范围（核心逻辑）
    private LocalDateTime[] calculateDateRange(String range) {
        LocalDateTime now = LocalDateTime.now();
        switch (range.toLowerCase()) {
            case "week":
                return new LocalDateTime[]{
                        now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY))
                                .withHour(0).withMinute(0).withSecond(0), // 本周一00:00:00
                        now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY))
                                .withHour(23).withMinute(59).withSecond(59) // 本周日23:59:59
                };
            case "month":
                return new LocalDateTime[]{
                        now.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0), // 本月第一天
                        now.with(TemporalAdjusters.lastDayOfMonth())
                                .withHour(23).withMinute(59).withSecond(59) // 本月最后一天
                };
            case "year":
                return new LocalDateTime[]{
                        now.withDayOfYear(1).withHour(0).withMinute(0).withSecond(0), // 本年第一天
                        now.with(TemporalAdjusters.lastDayOfYear())
                                .withHour(23).withMinute(59).withSecond(59) // 本年最后一天
                };
            default:
                throw new IllegalArgumentException("Invalid range parameter");
        }
    }

    // 数据合并与补零
    private List<StatsVo> mergeData(LocalDateTime start, LocalDateTime end,
                                    List<Map<String, Object>> cleanData,
                                    List<Map<String, Object>> analyzeData) {
        // 生成连续日期序列
        List<String> dateSeries = new ArrayList<>();
        LocalDate currentDate = start.toLocalDate();
        while (!currentDate.isAfter(end.toLocalDate())) {
            dateSeries.add(currentDate.toString());
            currentDate = currentDate.plusDays(1);
        }

        // 转换为Map便于查找
        Map<String, Integer> cleanMap = cleanData.stream()
                .collect(Collectors.toMap(
                        m -> m.get("date").toString(),
                        m -> Integer.parseInt(m.get("count").toString())
                ));
        Map<String, Integer> analyzeMap = analyzeData.stream()
                .collect(Collectors.toMap(
                        m -> m.get("date").toString(),
                        m -> Integer.parseInt(m.get("count").toString())
                ));

        // 构建完整结果
        return dateSeries.stream()
                .map(date -> new StatsVo()
                        .setDate(date)
                        .setCleanCount(cleanMap.getOrDefault(date, 0))
                        .setAnalCount(analyzeMap.getOrDefault(date, 0))
                )
                .collect(Collectors.toList());
    }
}
